package com.xyh.transaction.utils;

import com.xyh.transaction.common.Constant;
import com.xyh.transaction.entity.*;
import com.xyh.transaction.entity.dto.goods.GoodsInvoice;
import com.xyh.transaction.entity.dto.goods.GoodsInvoiceItem;
import com.xyh.transaction.exception.BusinessException;
import com.xyh.transaction.mapper.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.mail.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.thymeleaf.TemplateEngine;
import org.thymeleaf.context.Context;
import org.thymeleaf.templateresolver.ClassLoaderTemplateResolver;

import javax.mail.internet.MimeUtility;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.net.URL;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Date;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;

@Slf4j
@Component
public class EmailUtil {

    @Value("${email.hostName}")
    private String hostName;

    @Value("${email.sendEmail}")
    private String sendEmail;

    @Value("${email.password}")
    private String password;

    @Value("${email.adminEmail}")
    private String adminEmail;

    private static final AtomicInteger SEQUENCE = new AtomicInteger(0);
    private static final String TEMPLATE_SUFFIX = ".html";
    private static final String TEMPLATE_PATH = "email/";
    private static final DateTimeFormatter FORMATTER = DateTimeFormatter.ofPattern(Constant.DATE_FORMAT_DEFAULT);

    @Autowired
    private OrderMapper orderMapper;
    @Autowired
    private OrderDetailMapper orderDetailMapper;
    @Autowired
    private GoodsMapper goodsMapper;
    @Autowired
    private UserMapper userMapper;
    @Autowired
    private AddressMapper addressMapper;

    /**
     * 生成发票号
     */
    public static String generateInvoiceNumber(int orderId) {
        String datePart = new SimpleDateFormat("yyMMdd").format(new Date());
        String orderIdFormatted = String.format("%04d", orderId % 10000);
        String sequenceFormatted = String.format("%02d", SEQUENCE.incrementAndGet() % 100);
        return "IN" + datePart + orderIdFormatted + sequenceFormatted;
    }

    /**
     * 发送商品发票给买家
     */
    public void sendInvoiceToBuyer(String orderId, String subject) {
        try {
            // 查询订单和相关信息
            Order order = orderMapper.findById(Integer.valueOf(orderId));
            User buyer = userMapper.findById(order.getCreateBy());
            String invoiceNumber = generateInvoiceNumber(order.getId());
            List<GoodsInvoiceItem> items = buildInvoiceItems(order);
            GoodsInvoice goodsInvoice = buildGoodsInvoice(order, buyer, invoiceNumber, items);

            // 生成 PDF
            byte[] invoicePdf = PdfUtil.generatePdfBytes("pdf/fop.xconf", "pdf/goodsInvoice.fo", PdfUtil.convertToMap(goodsInvoice));

            // 配置邮件并发送
            HtmlEmail email = setupEmail(buyer.getEmail(), subject);
            email.setHtmlMsg(renderTemplate("invoiceTemplate", buyer.getUsername(), invoiceNumber, LocalDateTime.now().format(FORMATTER), order.getAmount(), adminEmail));
            email.attach(new ByteArrayDataSource(invoicePdf, "application/pdf"), "发票.pdf", "自动生成的发票");
            email.send();
            log.info("发票邮件发送成功，收件人：{}", buyer.getEmail());
        } catch (Exception e) {
            log.error("发票邮件发送失败：{}", e.getMessage(), e);
            throw new BusinessException("发票邮件发送失败！", e);
        }
    }

    /**
     * 发送商品信息给卖家
     */
    public void sendGoodsMsgToSeller(String receiverEmail, String subject, String message, String goodsImage, String goodsName, String orderNo, String orderAmount, String orderTime) {
        try {
            HtmlEmail email = setupEmail(receiverEmail, subject);
            email.setHtmlMsg(renderTemplate("goodsTemplate", message, orderNo, orderAmount, orderTime));

            EmailAttachment attachment = new EmailAttachment();
            attachment.setName(MimeUtility.encodeWord("商品" + goodsName + "图片.jpg", "UTF-8", "Q"));
            attachment.setDescription("商品图片");
            attachment.setDisposition(EmailAttachment.ATTACHMENT);
            attachment.setURL(new URL(goodsImage));
            email.attach(attachment);

            email.send();
            log.info("商品邮件发送成功，收件人：{}", receiverEmail);
        } catch (Exception e) {
            log.error("商品邮件发送失败：{}", e.getMessage(), e);
            throw new BusinessException("商品邮件发送失败！", e);
        }
    }

    /**
     * 发送异常信息给管理员
     */
    public void sendExceptionToAdmin(Exception e) {
        try {
            HtmlEmail email = setupEmail(adminEmail, "系统异常通知");
            email.setHtmlMsg(renderTemplate("exceptionTemplate", e.getClass().getName(), e.getMessage(), LocalDateTime.now().format(FORMATTER)));
            email.send();
            log.info("系统异常通知邮件发送成功！");
        } catch (Exception ex) {
            log.error("系统异常通知邮件发送失败：{}", ex.getMessage(), ex);
            throw new BusinessException("系统异常通知邮件发送失败！", ex);
        }
    }

    /**
     * 通用邮件配置
     */
    private HtmlEmail setupEmail(String to, String subject) throws EmailException {
        HtmlEmail email = new HtmlEmail();
        email.setHostName(hostName);
        email.setAuthentication(sendEmail, password);
        email.setSmtpPort(587); // TLS 端口
        email.setStartTLSEnabled(true);
        email.addTo(to);
        email.setFrom(sendEmail, "易物校园系统", "utf-8");
        email.setSubject(subject);
        email.setCharset("utf-8");
        return email;
    }

    /**
     * 渲染模板
     */
    private String renderTemplate(String templateName, Object... variables) {
        ClassLoaderTemplateResolver templateResolver = new ClassLoaderTemplateResolver();
        templateResolver.setTemplateMode("HTML");
        templateResolver.setSuffix(TEMPLATE_SUFFIX);

        TemplateEngine templateEngine = new TemplateEngine();
        templateEngine.setTemplateResolver(templateResolver);

        Context context = new Context();
        if (variables != null && variables.length > 0) {
            for (int i = 0; i < variables.length; i++) {
                context.setVariable("var" + i, variables[i]);
            }
        }
        return templateEngine.process(TEMPLATE_PATH + templateName, context);
    }

    /**
     * 构建发票条目
     */
    private List<GoodsInvoiceItem> buildInvoiceItems(Order order) {
        return orderDetailMapper.findByOrderId(order.getId()).stream().map(detail -> {
            Goods goods = goodsMapper.findById(detail.getGoodsId());
            GoodsInvoiceItem item = new GoodsInvoiceItem();
            item.setGoodsName(goods.getName());
            item.setUnit("个");
            item.setTaxRate("10%");
            BigDecimal quantity = new BigDecimal(detail.getCount());
            BigDecimal price = goods.getPrice();
            item.setTaxAmount(price.multiply(quantity).multiply(new BigDecimal("0.1")).toString());
            item.setTotalPrice(price.multiply(quantity).toString());
            return item;
        }).collect(Collectors.toList());
    }

    /**
     * 构建发票
     */
    private GoodsInvoice buildGoodsInvoice(Order order, User buyer, String invoiceNumber, List<GoodsInvoiceItem> items) {
        BigDecimal totalAmount = order.getAmount().setScale(2, RoundingMode.HALF_UP);
        BigDecimal totalTax = totalAmount.multiply(new BigDecimal("0.1")).setScale(2, RoundingMode.HALF_UP);

        GoodsInvoice invoice = new GoodsInvoice();
        invoice.setBuyerName(buyer.getUsername());
        invoice.setInvoiceNumber(invoiceNumber);
        invoice.setItems(items);
        invoice.setTotalAmount("¥" + totalAmount);
        invoice.setTotalTax("¥" + totalTax);
        invoice.setTotalInDigits("¥" + totalAmount.add(totalTax));
        invoice.setTotalInWords(AmountConverter.convertToChinese(totalAmount.add(totalTax)));
        invoice.setIssueDate(LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
        return invoice;
    }

    public static void main(String[] args) {
        EmailUtil emailUtil = new EmailUtil();
//        emailUtil.sendInvoiceToBuyer("1", "测试");
//        emailUtil.sendGoodsMsgToSeller("1", "测试", "测试", "http://www.baidu.com", "测试商品", "123456789", "100.00", "2021-01-01 12:00:00");
        emailUtil.sendExceptionToAdmin(new Exception("测试异常"));
    }
}
